# -*- coding: utf-8 -*-

from openerp.addons.web import http
from openerp.addons.web.http import request
from openerp import SUPERUSER_ID
from openerp.http import HttpRequest, JsonRequest
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT

from openerp.osv import osv
import simplejson
import itertools
import datetime
import math
from functools import wraps


class VueMshop(http.Controller):

    def check_shop(method):
        @wraps(method)
        def func(self, shop=False, *args, **kwargs):
            cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
            shop_obj = pool.get('shop')

            if not hasattr(request, 'make_response'):
                shop = self._get_json_data().get('shop')

            if not shop:
                return self.error_response(u'必须指定一个商城')

            shop_ids = shop_obj.search(cr, uid, [('code', '=', shop)], context=context)
            if not shop_ids:
                return self.error_response(u'当前商城%s不存在' % shop)

            # if not shop_obj.check_user_access(cr, uid, shop_ids, uid, context=context):
                # return self.error_response(u'当前用户没有权限访问当前商城，请联系管理员')

            request.session['shop_id'] = shop_ids[0]
            return method(self, *args, **kwargs)

        return func

    @check_shop
    @http.route('/vue/mshop/get_config_shop_type')
    def get_config_shop_type(self):
        cr, context, pool = request.cr, request.context, request.registry
        shop = pool.get('shop').browse(cr, SUPERUSER_ID, request.session['shop_id'], context=context)

        return request.make_response(simplejson.dumps({
            'type': shop.type,
            'name': shop.name,
            'ratio': shop.redeem_ratio,
        }))

    @check_shop
    @http.route('/vue/mshop/get_user')
    def get_user(self):
        cr, uid, context, pool = request.cr, request.uid, request.context, request.registry

        user = pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context=context)

        def check_pay(order_ids):
            return len([order.id for order in pool.get('sale.order').browse(
                cr, SUPERUSER_ID, order_ids, context=context) if not order.invoiced])

        return request.make_response(simplejson.dumps({
            'user': {
                'img': '/website/image/res.users/%s/image' % user.id,
                'name': user.name
            },
            'badges': [
                str(self._calculate_max(user.partner_id.id, 'draft')),
                str(check_pay(self._calculate_order_ids(user.partner_id.id, 'pay', limit=10000))),
                str(self._calculate_max(user.partner_id.id, 'delivery')),
                str(self._calculate_max(user.partner_id.id, 'done')),
                '0'
            ],
            'point_balance': user.partner_id.point_balance or 0,
        }))

    @check_shop
    @http.route('/vue/mshop/get_article_categ')
    def get_article_categ(self):
        cr, context, pool = request.cr, request.context, request.registry
        shop = pool.get('shop').browse(cr, SUPERUSER_ID,
                                       request.session['shop_id'], context=context)
        return request.make_response(simplejson.dumps([
            {'id': category.id, 'name': category.name} for category in shop.article_categ_ids
        ]))

    def _handle_product_value(self, value):
        cr, context, pool = request.cr, request.context, request.registry

        product = pool.get('product.template').browse(
            cr, SUPERUSER_ID, int(value.get('model_id')), context=context)

        return simplejson.dumps({
            'id': product.id,
            'src': '/website/image/product.template/%s/image' % product.id,
            'price': product.list_price,
        })

    def _get_ad_wall_component(self, value):
        cr, context, pool = request.cr, request.context, request.registry

        wall = pool.get('mshop.ad.wall').browse(
            cr, SUPERUSER_ID, int(value.get('model_id')), context=context)

        return wall.type == 'big' and 'carousel' or 'h-scroller'

    def _handle_ad_value(self, value):
        cr, context, pool = request.cr, request.context, request.registry

        wall = pool.get('mshop.ad.wall').browse(
            cr, SUPERUSER_ID, int(value.get('model_id')), context=context)

        return simplejson.dumps([{
            'id': line.id,
            'img': '/website/image/mshop.ad.wall.line/%s/image' % line.id,
            'url': pool.get('mshop.ad.wall.line').get_url(cr, SUPERUSER_ID, line, context=context),
            'title': line.name,
        } for line in wall.line_ids])

    def _handle_article_value(self, value):
        cr, context, pool = request.cr, request.context, request.registry

        article = pool.get('mshop.article').browse(
            cr, SUPERUSER_ID, int(value.get('model_id')), context=context)

        return simplejson.dumps({
            'article': article.id,
            'src': '/website/image/mshop.article/%s/image' % article.id,
            'title': article.name,
        })

    def _get_row_value(self, row):
        if row.component == 'image-input':
            return '/' + row.value

        if row.component != 'many2one-input':
            return row.value

        value = simplejson.loads(row.value)

        value_model_map = {
            'product.template': self._handle_product_value,
            'mshop.ad.wall': self._handle_ad_value,
            'mshop.article': self._handle_article_value
        }

        if value.get('model') not in value_model_map:
            raise IndexError(u'错误，当前的model %s 未定义' % value.get('model'))

        return value_model_map.get(value.get('model'))(value)

    def _get_row_component(self, row):
        if row.component != 'many2one-input':
            return row.component

        component_model_map = {
            'product.template': lambda value: 'product',
            'mshop.ad.wall': self._get_ad_wall_component,
            'mshop.article': lambda value: 'article-input'
        }

        value = simplejson.loads(row.value)

        if value.get('model') not in component_model_map:
            raise IndexError(u'错误，当前的model %s 未定义' % value.get('model'))

        return component_model_map.get(value.get('model'))(value)

    def _get_product_price(self, product):
        prices = []
        for product in product.product_variant_ids:
            prices.append(product.lst_price)

        distinguish_prices = list(set(prices))
        if len(distinguish_prices) == 1:
            return distinguish_prices[0]
        else:
            return '%s-%s' % (min(distinguish_prices), max(distinguish_prices))

    def _get_product_imgs(self, product):
        res = [{'img': '/website/image/product.template/%s/image' % product.id}]
        for product in itertools.islice(product.product_variant_ids, 0, 12):
            if (product.image):
                res.append({
                    'img': '/website/image/product.product/%s/image' % product.id
                })

        return simplejson.dumps(res)

    def _get_product_varaint(self, product):
        res = []
        for product in product.product_variant_ids:
            res.append({
                'id': product.id,
                'name': product.name,
                'price': product.lst_price,
                'stock': product.qty_available,
                'uom': product.uom_id.name,
                'img': '/website/image/product.product/%s/image' % product.id,
                'variant': {
                    attribute.attribute_id.name: attribute.name for attribute in \
                    product.attribute_value_ids
                }
            })
        return simplejson.dumps(res)

    @check_shop
    @http.route('/vue/mshop/get_product')
    def get_product(self, product):
        cr, context, pool = request.cr, request.context, request.registry

        product = pool.get('product.template').browse(cr, SUPERUSER_ID, int(product), context=context)
        return request.make_response(simplejson.dumps({
            'id': product.id,
            'variant_id': product.product_variant_ids[0].id,
            'name': product.name,
            'desc': product.description or '',
            'price': self._get_product_price(product),
            'uom': product.uom_id.name,
            'stock': product.qty_available,
            'img': '/website/image/product.template/%s/image' % product.id,
            'imgs': self._get_product_imgs(product),
            'variant': self._get_product_varaint(product)
        }))

    def _search_products_sql(self, categ_id=None, offset=0, querys=None, order='', direction='', limit=10, calcu_max=False):
        sql_text = '''
            SELECT %s
            FROM shop_line line
            LEFT JOIN product_template template ON line.product_id = template.id
            WHERE %s
            %s
        '''

        domain = [
            'line.shop_id = %s' % request.session['shop_id'],
            'line.is_online = True'
        ]
        if categ_id:
            domain.append('''
                template.id in (
                    select product_template_id
                    from product_public_category_product_template_rel
                    where product_public_category_id = %s)
            ''' % categ_id)

        if querys:
            query_str = ','.join(map(lambda query: "'%%%s%%'" % query, querys.split(' ')))
            domain.append('template.name ilike all (array[%s])' % query_str)

        _order = 'line.sequence DESC'
        if order:
            _order_map = {
                u'综合': 'line.sequence',
                u'销量': 'line.sequence',  # 暂时没有这个统计信息 @zzx TODO
                u'价格': 'template.list_price',
            }
            _order = _order_map.get(order, 'line.sequence') + ' ' + (direction == 'up' and 'ASC' or 'DESC') + ',template.name'

        if calcu_max:
            return sql_text % ('COUNT(*)', ' AND '.join(domain), '')
        else:
            return sql_text % ('template.id', ' AND '.join(domain),
                               'ORDER BY %s LIMIT %s OFFSET %s' % (_order, limit, offset))

    def _calculate_product_ids(self, categ_id=None, offset=0, querys=None, order='', direction='', limit=10):
        sql_text = self._search_products_sql(categ_id, offset, querys, order, direction, limit)

        request.cr.execute(sql_text)

        res = request.cr.fetchall()
        return map(lambda item: item[0], res)

    def _calculate_product_max(self, categ_id=None, querys=None):
        sql_text = self._search_products_sql(categ_id=categ_id, querys=querys, calcu_max=True)

        request.cr.execute(sql_text)
        return request.cr.fetchall()[0]

    @check_shop
    @http.route('/vue/mshop/get_products')
    def get_products(self, options):
        cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
        options = simplejson.loads(options)
        user = pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context=context)
        shop = pool.get('shop').browse(cr, SUPERUSER_ID, request.session.get('shop_id'), context=context)

        product_ids = self._calculate_product_ids(**options)

        product_max = 0
        categorys = []
        if int(options.get('offset')) == 0:
            product_max = self._calculate_product_max(options.get('categ_id'), options.get('querys'))
            if shop and shop.type == 'integral':
                for category in shop.categ_ids:
                    categorys.append({
                        'id': category.id,
                        'name': category.name,
                        'image': '/website/image/product.public.category/%s/image' % category.id,
                    })

        products = []
        for product in pool.get('product.template').browse(cr, SUPERUSER_ID, product_ids, context=context):
            products.append({
                'id': product.id,
                'image': '/website/image/product.template/%s/image' % product.id,
                'name': product.name,
                'price': product.list_price,
            })

        return request.make_response(simplejson.dumps({
            'products': products,
            'categorys': categorys,
            'categ_id': options.get('categ_id'),
            'max': product_max,
        }))

    @check_shop
    @http.route('/vue/mshop/get_product_article')
    def get_product_article(self, product):
        cr, context, pool = request.cr, request.context, request.registry

        return request.make_response(simplejson.dumps(
            [{
                'id': row.id,
                'index': row.index,
                'value': self._get_row_value(row),
                'component': self._get_row_component(row),
            } for row in pool.get('product.template').browse(
                cr, SUPERUSER_ID, int(product), context=context).description_editor_ids]
        ))

    @check_shop
    @http.route('/vue/mshop/get_article')
    def get_article(self, article=None):
        cr, context, pool = request.cr, request.context, request.registry
        shop = pool.get('shop').browse(cr, SUPERUSER_ID, request.session.get('shop_id'), context=context)

        article_obj = pool.get('mshop.article')
        if not article:
            article_id = article_obj.search(cr, SUPERUSER_ID, [
                ('is_home', '!=', False),
                ('shop_id', '=', request.session.get('shop_id'))],
                order='id', limit=1, context=context)
        else:
            article_id = int(article)

        if article_id and isinstance(article_id, (list, tuple)):
            article_id = article_id[0]

        if not article_id:
            return self.error_response(u'错误, 没有找到首页配置')

        return request.make_response(simplejson.dumps(
            [{
                'id': row.id,
                'index': row.index,
                'value': self._get_row_value(row),
                'component': self._get_row_component(row),
            } for row in article_obj.browse(
                cr, SUPERUSER_ID, article_id, context=context).line_ids]
        ))

    @check_shop
    @http.route('/vue/mshop/get_article_header')
    def get_article_header(self, article):
        cr, context, pool = request.cr, request.context, request.registry

        article = pool.get('mshop.article').browse(
            cr, SUPERUSER_ID, int(article), context=context)
        return request.make_response(simplejson.dumps({
            'title': article.name,
            'src': '/website/image/mshop.article/%s/image' % article.id
        }))

    @check_shop
    @http.route('/vue/mshop/get_articles_by_category')
    def get_articles_by_category(self, categ_id):
        cr, context, pool = request.cr, request.context, request.registry
        article_obj = pool.get('mshop.article')

        article_ids = article_obj.search(cr, SUPERUSER_ID, [
            ('categ_id', '=', int(categ_id)),
            ('shop_id', '=', request.session.get('shop_id'))
        ], context=context)

        return request.make_response(simplejson.dumps(
            [{
                'article': article.id,
                'src': '/website/image/mshop.article/%s/image' % article.id,
                'title': article.name,
            } for article in article_obj.browse(
                cr, SUPERUSER_ID, article_ids, context=context)]
        ))

    def _set_get_cart(self, get_cart=True):
        request.session['get_cart'] = get_cart

    def _get_json_data(self):
        return request.jsonrequest

    def error_response(self, data, status=500):
        if hasattr(request, 'make_response'):
            temp = request.make_response(data)
            temp.status_code = status

            return temp
        else:
            return simplejson.dumps({
                'data': data,
                'status': status,
                'ok': True,
            })

    # TODO 现在使用是website强相关的商城购物车
    @check_shop
    @http.route('/vue/mshop/get_cart', website=True)
    def get_cart(self):
        self._set_get_cart(True)
        cart = request.website.sale_get_order()

        return request.make_response(simplejson.dumps(
                cart.get_cart_line_info(context=request.context)
            ))

    @check_shop
    @http.route('/vue/mshop/add_cart_line', type='json', website=True)
    def add_cart_line(self):
        params = self._get_json_data()

        self._set_get_cart(True)
        cart = request.website.sale_get_order()
        cart._cart_update(product_id=params.get('product_id'), add_qty=params.get('qty'))

    @check_shop
    @http.route('/vue/mshop/update_cart_qty', type='json')
    def update_cart_qty(self):
        cr, context, pool = request.cr, request.context, request.registry
        params = self._get_json_data()

        pool.get('shopping.cart.line').write(cr, SUPERUSER_ID,
                                             params.get('cart_id'),
                                             {'product_uom_qty': params.get('qty')},
                                             context=context)

    @check_shop
    @http.route('/vue/mshop/delete_cart', type='json')
    def delete_cart(self):
        cr, context, pool = request.cr, request.context, request.registry
        params = self._get_json_data()

        pool.get('shopping.cart.line').write(cr, SUPERUSER_ID,
                                             params.get('cart_id'),
                                             {'state': 'delete'},
                                             context=context)

    @check_shop
    @http.route('/vue/mshop/get_addresss')
    def get_addresss(self):
        cr, uid, context, pool = request.cr, request.uid, request.context, request.registry

        user = pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context=context)
        return request.make_response(simplejson.dumps(
            pool.get('customer.address').get_addresss_by_partner(
                cr, SUPERUSER_ID, user.partner_id.id, context=context)
        ))

    @check_shop
    @http.route('/vue/mshop/get_address')
    def get_address(self, address_id):
        cr, context, pool = request.cr, request.context, request.registry

        return request.make_response(simplejson.dumps(
            pool.get('customer.address').get_address(
                cr, SUPERUSER_ID, int(address_id), context=context)
        ))

    @check_shop
    @http.route('/vue/mshop/get_default_address')
    def get_default_address(self):
        cr, uid, context, pool = request.cr, request.uid, request.context, request.registry

        user = pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context=context)

        return request.make_response(simplejson.dumps(
            pool.get('customer.address').get_default_address(
                cr, SUPERUSER_ID, user.partner_id.id, context=context)
        ))

    @check_shop
    @http.route('/vue/mshop/save_address', type='json')
    def save_address(self):
        cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
        params = self._get_json_data()

        def format_value(address):
            return {
                'name': address.get('name'),
                'phone': address.get('phone'),
                'zip': address.get('zip'),
                'street': address.get('street'),
                'province_id': address.get('address')[0].split('-')[-1],
                'city_id': address.get('address')[1].split('-')[-1],
                'county_id': address.get('address')[2].split('-')[-1],
            }

        address = params.get('address')
        if params.get('address_id'):
            pool.get('customer.address').write(
                cr, SUPERUSER_ID, int(params.get('address_id')), format_value(address), context=context)
        else:
            user = pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context=context)
            pool.get('customer.address').create(
                cr, SUPERUSER_ID, dict(format_value(address),
                                       partner_id=user.partner_id.id),
                context=context)

    @check_shop
    @http.route('/vue/mshop/delete_address', type='json')
    def delete_address(self):
        cr, context, pool = request.cr, request.context, request.registry
        params = self._get_json_data()

        pool.get('customer.address').write(cr, SUPERUSER_ID,
                                           params.get('address_id'),
                                           {'state': 'cancel'},
                                           context=context)

    @check_shop
    @http.route('/vue/mshop/choose_address', type='json')
    def choose_address(self):
        cr, context, pool = request.cr, request.context, request.registry
        params = self._get_json_data()

        pool.get('customer.address').set_default(cr, SUPERUSER_ID,
                                                 params.get('address_id'),
                                                 context=context)

    def _get_order_detail(self, order):
        def get_current_state():
            if order.state == 'draft':
                return '意向单'
            elif order.state == 'done':
                return '已完成'
            elif order.state == 'cancel':
                return '已取消'
            else:
                return '待收货'

        res = {
            'id': order.id,
            'name': order.name,
            'state': order.state,
            'redeem_ratio': order.redeem_ratio,
            'current_state': get_current_state(),
            'invoiced': order.invoiced,
            'shipping_date': order.expected_delivery_time,
            'message': order.note,
            'amount': order.amount_total,
            'amount_tax': order.amount_tax,
            'create_date': datetime.datetime.strftime(datetime.datetime.strptime(
                order.create_date, DEFAULT_SERVER_DATETIME_FORMAT
            ) + datetime.timedelta(hours=8), DEFAULT_SERVER_DATETIME_FORMAT),  # 修复时区的问题
            'order_line': [{
                'product_img': '/website/image/product.product/%s/image' % line.product_id.id,
                'name': line.product_id.name,
                'variant': ' '.join('%s: %s' % (attr.attribute_id.name, attr.name) for attr in line.product_id.attribute_value_ids),
                'price_unit': line.price_unit,
                'product_uom_qty': line.product_uom_qty,
            } for line in order.order_line]
        }

        res.update({
            'amount_qty': sum(line.get('product_uom_qty', 0) for line in res.get('order_line'))
        })

        return res

    def _search_orders_sql(self, partner_id, state='', offset=0, querys=None, calcu_max=False, limit=10):
        sql_text = '''
            select %s
                FROM sale_order_line line
                LEFT JOIN sale_order sale_order ON line.order_id = sale_order.id
                LEFT JOIN product_product product ON line.product_id = product.id
                WHERE %s
                GROUP BY sale_order.id
                %s
            '''

        domain = [
            'sale_order.shop_id = %s' % request.session.get('shop_id'),
            'sale_order.partner_id = %s' % partner_id
        ]
        if state:
            if state in ('pay', 'delivery'):
                domain.append("sale_order.state not in ('draft', 'cancel', 'done')")
            else:
                domain.append("sale_order.state = '%s'" % state)

        if querys:
            query_str = ','.join(map(lambda query: "'%%%s%%'" % query, querys.split(' ')))
            domain.append('''
                (sale_order.name ilike all (array[%s])
                OR product.name_template ilike all (array[%s]) )
            ''' % (query_str, query_str))

        if calcu_max:
            return sql_text % ('COUNT(*)', ' AND '.join(domain), '')
        else:
            return sql_text % ('sale_order.id', ' AND '.join(domain),
                               'ORDER BY sale_order.id DESC LIMIT %s OFFSET %s' % (limit, offset))

    def _calculate_order_ids(self, partner_id, state='', offset=0, querys=None, limit=10):
        sql_text = self._search_orders_sql(partner_id, state, offset, querys, limit=10)
        request.cr.execute(sql_text)

        res = request.cr.fetchall()
        return map(lambda item: item[0], res)

    def _calculate_max(self, partner_id, state='', querys=None):
        sql_text = self._search_orders_sql(partner_id, state, querys=querys, calcu_max=True)

        request.cr.execute(sql_text)
        return len(request.cr.fetchall())

    @check_shop
    @http.route('/vue/mshop/get_orders')
    def get_orders(self, offset=0, state='', querys=''):
        cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
        user = pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context=context)

        def check_pay(order_ids):
            return len([order.id for order in pool.get('sale.order').browse(
                cr, uid, order_ids, context=context) if not order.invoiced])

        order_ids = self._calculate_order_ids(user.partner_id.id, state, int(offset), querys)

        order_max = 0
        if int(offset) == 0:
            if state == 'pay':
                order_max = check_pay(self._calculate_order_ids(user.partner_id.id, state='pay', querys=querys, limit=10000))
            else:
                order_max = self._calculate_max(user.partner_id.id, state, querys)

        orders = []
        for order in pool.get('sale.order').browse(cr, SUPERUSER_ID, order_ids, context=context):
            if state != 'pay' or not order.invoiced:
                orders.append(self._get_order_detail(order))

        return request.make_response(simplejson.dumps({
            'orders': orders,
            'state': state,
            'max': order_max,
        }))

    @check_shop
    @http.route('/vue/mshop/get_order')
    def get_order(self, order_id):
        cr, uid, context, pool = request.cr, request.uid, request.context, request.registry

        order_id = order_id and int(order_id) or request.session['sale_order_id']
        if not order_id:
            raise ValueError(u'错误，没有找到相关的单据')

        order = pool.get('sale.order').browse(cr, SUPERUSER_ID, order_id, context=context)

        res = self._get_order_detail(order)
        res.update({
            'address': {
                'name': order.consignee,
                'phone': order.mobile_number,
                'province_id': {'name': order.province_id.name or ''},
                'city_id': {'name': order.city_id.city_name or ''},
                'county_id': {'name': order.county_id.county_name or ''},
                'street': order.street
            }
        })

        return request.make_response(simplejson.dumps(res))

    @check_shop
    @http.route('/vue/mshop/delete_order', type='json')
    def delete_order(self):
        cr, context, pool = request.cr, request.context, request.registry
        params = self._get_json_data()

        if params.get('order_id'):
            pool.get('sale.order').action_cancel(cr, SUPERUSER_ID, [int(params.get('order_id'))], context=context)

    def _get_start_date(self):
        cr, context, pool = request.cr, request.context, request.registry
        minmum_days = pool.get('ir.config_parameter').get_param(
            cr, SUPERUSER_ID, 'mshop.minimum_interval_delivery_days') or 3

        try:
            minmum_days = int(minmum_days)
        except ValueError:
            minmum_days = 3

        return datetime.date.strftime(
            datetime.date.today() + datetime.timedelta(days=minmum_days), '%Y-%m-%d')

    def _compute_price(self, price):
        cr, context, pool = request.cr, request.context, request.registry
        shop = pool.get('shop').browse(cr, SUPERUSER_ID, request.session['shop_id'], context=context)

        if shop == 'integral':
            return math.ceil(price)

        return price

    @check_shop
    @http.route('/vue/mshop/get_temp_order', website=True)
    def get_temp_order(self, cart_ids='', product=''):
        cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
        order_line = []
        if cart_ids:
            cart_ids = simplejson.loads(cart_ids)

            self._set_get_cart(True)
            cart = request.website.sale_get_order()

            for line in cart.cart_line:
                if line.id in cart_ids:
                    order_line.append({
                        'id': line.id,
                        'product_img': '/website/image/product.product/%s/image' % line.product_id.id,
                        'name': line.product_id.name,
                        'variant': ' '.join('%s: %s' % (attr.attribute_id.name, attr.name) for attr in line.product_id.attribute_value_ids),
                        'price_unit': self._compute_price(line.price_unit),
                        'product_uom_qty': line.product_uom_qty
                    })
        elif product:
            product = simplejson.loads(product)
            product_browse = pool.get('product.product').browse(cr, SUPERUSER_ID,
                                                                int(product.get('product_id')),
                                                                context=context)
            order_line.append({
                'id': product_browse.id,
                'product_img': '/website/image/product.product/%s/image' % product_browse.id,
                'name': product_browse.name,
                'variant': ' '.join('%s: %s' % (attr.attribute_id.name, attr.name) for attr in product_browse.attribute_value_ids),
                'price_unit': self._compute_price(product_browse.list_price),  # TODO @zzx 价格策略
                'product_uom_qty': product.get('product_qty'),
            })

        return request.make_response(simplejson.dumps({
            'order_line': order_line,
            'start_date': self._get_start_date()
        }))

    @check_shop
    @http.route('/vue/mshop/test_can_pay')
    def test_can_pay(self, amount):
        cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
        shop = pool.get('shop').browse(cr, SUPERUSER_ID, request.session['shop_id'], context=context)

        user = pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context=context)

        if user.partner_id.point_balance < float(amount) * shop.redeem_ratio:
            return self.error_response('当前积分不够兑换选中物品')

    @check_shop
    @http.route('/vue/mshop/create_order', type='json', website=True)
    def create_order(self):
        cr, uid, context, pool = request.cr, request.uid, request.context, request.registry
        shop = pool.get('shop').browse(cr, SUPERUSER_ID, request.session['shop_id'], context=context)
        params = self._get_json_data()

        sale_id = False

        address = pool.get('customer.address').browse(
            cr, SUPERUSER_ID, int(params.get('address_id')), context=context)

        def get_value_from_pram():
            return {
                'expected_delivery_time': params.get('shipping_date', ''),
                'note': params.get('message', ''),
                'consignee': address.name,
                'province_id': address.province_id.id,
                'city_id': address.city_id.id,
                'county_id': address.county_id.id,
                'street': address.street,
                'zip': address.zip,
                'mobile_number': address.phone,
                'shipping_type_sale': 'self_logistics',  # 暂时默认公司物流
            }

        if params.get('cart_ids'):
            cart_ids = simplejson.loads(params.get('cart_ids', ''))

            cart = request.website.sale_get_order()
            sale_id = pool.get('shopping.cart').create_partial_sale_order(
                cr, SUPERUSER_ID, cart, cart_ids, value=get_value_from_pram(),
                context=dict(context, ceil=(shop.type == 'integral')))

        elif params.get('product'):
            product = simplejson.loads(params.get('product', ''))

            sale_id = pool.get('shopping.cart').create_sale_order_by_product(
                cr, uid, int(product.get('product_id')),
                float(product.get('product_qty')), value=get_value_from_pram(),
                context=dict(context, ceil=(shop.type == 'integral')))

        request.session['sale_order_id'] = sale_id

        if shop.type == 'integral':
            order = pool.get('sale.order').browse(cr, SUPERUSER_ID, sale_id, context=context)
            order.action_button_confirm()
            stock_locked = order.locked_inventory_operation()
            if not stock_locked:
                cr.rollback()
                return self.error_response(u'错误，此库存不足无法兑换, 请更换其他产品')
                #raise ValueError(u'错误，此库存不足无法兑换, 请更换其他产品')
            order.manual_invoice()
            order.invoice_ids.signal_workflow('invoice_open')
            order.change_points()

        return simplejson.dumps({
            'sale_id': sale_id
        })

    @check_shop
    @http.route('/vue/mshop/get_categorys')
    def get_categorys(self):
        cr, context, pool = request.cr, request.context, request.registry
        shop = pool.get('shop').browse(cr, SUPERUSER_ID, request.session['shop_id'], context=context)

        menus = []
        contents = {}

        for category in shop.categ_ids:
            if category.parent_id:
                if category.parent_id.id not in contents:
                    menus.append({
                        'id': category.parent_id.id,
                        'name': category.parent_id.name,
                    })

                    contents[category.parent_id.id] = {
                        'id': category.parent_id.id,
                        'name': category.parent_id.name,
                        'categorys': []
                    }

                contents[category.parent_id.id]['categorys'].append({
                    'img': '/website/image/product.public.category/%s/image_medium' % category.id,
                    'id': category.id,
                    'name': category.name
                })

        if not menus:
            return self.error_response(u'错误，没有找到相关的分类配置')

        res_contents = []
        for menu in menus:
            res_contents.append(dict(contents[menu.get('id')], id=menu.get('id')))

        return request.make_response(simplejson.dumps({
            'menus': menus,
            'contents': res_contents,
            'current_menu': menus[0].get('id'),
        }))
